/*

Frequency of use: 1 2 3 4 [5] HIGH

Short:
    An abstract factory is used to create objects.  However you want to change 
    what object is created.

Long:
    A software design pattern, the Abstract Factory Pattern provides a way to 
encapsulate a group of individual factories that have a common theme.
In normal usage, the client software creates a concrete implementation of the 
abstract factory and then uses the eneric interfaces to create the concrete 
objects that are part of the theme. The client does not know (or care) which 
concrete objects it gets from each of these internal factories since it uses 
only the generic interfaces of their products. This pattern separates the 
details of implementation of a set of objects from their general usage.

Information sources:
 - http://calumgrant.net/patterns/index.html
 - http://en.wikipedia.org/wiki/Abstract_factory_pattern
 - http://www.dofactory.com/Patterns/Patterns.aspx
*/

#include <iostream>
#include <string>
#include <memory>

class Message
{
public:
	virtual ~Message() { }
	virtual std::string get_message()=0;
};

class MessageFactory
{
public:
	virtual ~MessageFactory() { }
	virtual std::auto_ptr<Message> create_message() const=0;
};

class HelloWorldMessage : public Message
{
public:
	std::string get_message()
	{
		return "Hello world!";
	}
};

class HelloWorldFactory : public MessageFactory
{
public:
	std::auto_ptr<Message> create_message() const
	{
		return std::auto_ptr<Message>(new HelloWorldMessage());
	}
};

void hello_world(const MessageFactory & factory)
{
	std::auto_ptr<Message> message = factory.create_message();
	std::cout << message->get_message() << std::endl;
}

int main()
{
	hello_world(HelloWorldFactory());
	return 0;
}
